package com.ys.filelib.filedialog.ftp;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.IOException;

/**
 * FTP 工具类
 */
public class FTPHelper {

    private FTPClient mFtpClient;
    private String mHost;
    private String mUserName;
    private String mPassword;
    private String mPath;
    private int mPort;

    public static FTPHelper create(String addr, int port, String username, String password) {
        FTPHelper helper = new FTPHelper();
        helper.mHost = addr;
        helper.mPort = port;
        helper.mUserName = username;
        helper.mPassword = password;
        return helper;
    }

    /**
     * 连接 FTP 服务器
     * @param addr     FTP 服务器 IP 地址
     * @param port     FTP 服务器端口号
     * @param username 登录用户名
     * @param password 登录密码
     */
    public boolean connectFtp(String addr, int port, String username, String password) {
        this.mHost = addr;
        this.mUserName = username;
        this.mPassword = password;
        this.mPort = port;
        if (mFtpClient == null) {
            mFtpClient = new FTPClient();
            //设置文件传输的编码
            mFtpClient.setControlEncoding("GBK");
            mFtpClient.setDefaultTimeout(10000);
            mFtpClient.setDataTimeout(10000);
            mFtpClient.setConnectTimeout(10000);
        }
        return connect();
    }

    public boolean connect() {
        if (mFtpClient == null) {
            return connectFtp(mHost, mPort, mUserName, mPassword);
        }
        try {
            /**连接 FTP 服务器
             * 如果连接失败，则此时抛出异常，如ftp服务器服务关闭时，抛出异常：
             * java.net.ConnectException: Connection refused: connect*/
            mFtpClient.connect(mHost, mPort);
            /**登录 FTP 服务器
             * 1）如果传入的账号为空，则使用匿名登录，此时账号使用 "Anonymous"，密码为空即可*/
            boolean loginOk;
            if (mUserName == null || mUserName.trim().isEmpty()) {
                loginOk = mFtpClient.login("Anonymous", "");
            } else {
                loginOk = mFtpClient.login(mUserName, mPassword);
            }

            /** 设置传输的文件类型
             * BINARY_FILE_TYPE：二进制文件类型
             * ASCII_FILE_TYPE：ASCII传输方式，这是默认的方式
             * ....
             */
            mFtpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

            /**
             * 确认应答状态码是否正确完成响应
             * 凡是 2开头的 isPositiveCompletion 都会返回 true，因为它底层判断是：
             * return (reply >= 200 && reply < 300);
             */
            System.out.println(">>>>>FTP reply============= " + loginOk);
            if (loginOk) {
                mFtpClient.enterLocalPassiveMode();
                mPath = mFtpClient.printWorkingDirectory();
                System.out.println(">>>>>FTP printWorkingDirectory============= " + mPath);
                return true;
            } else {
                mFtpClient.abort();
                mFtpClient.disconnect();
            }
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(">>>>>FTP服务器连接登录失败，请检查连接参数是否正确，或者网络是否通畅*********");
        }
        return false;
    }

    public void reconnect() {
        disconnect();
        connect();
    }

    /**
     * 使用完毕，应该及时关闭连接
     * 终止 ftp 传输
     * 断开 ftp 连接
     */
    public void disconnect() {
        try {
            if (mFtpClient != null && mFtpClient.isConnected()) {
                mFtpClient.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isConnected() {
        return mFtpClient != null && mFtpClient.isConnected();
    }

    public FTPClient getFtpClient() {
        return mFtpClient;
    }

    public FTPFile[] listFiles() throws IOException {
        return mFtpClient != null ? mFtpClient.listFiles() : null;
    }

    public FTPFile[] listFiles(String pathName) {
        try {
            return mFtpClient.listFiles(pathName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean changeDirectory(String pathName) throws IOException {
        if (mFtpClient != null) {
            return mFtpClient.changeWorkingDirectory(pathName);
        }
        return false;
    }

    public String getCurrentDir() {
        if (mFtpClient != null) {
            try {
                return mFtpClient.printWorkingDirectory();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    public String getPath() {
        return mPath;
    }

    public String getHost() {
        return mHost;
    }

    public String getUserName() {
        return mUserName;
    }

    public String getPassword() {
        return mPassword;
    }

    public int getPort() {
        return mPort;
    }
}